View Javadoc
1   package org.apache.maven.surefire.testng.conf;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.lang.reflect.Method;
23  import java.util.ArrayList;
24  import java.util.HashMap;
25  import java.util.Iterator;
26  import java.util.Map;
27  
28  import org.apache.maven.surefire.booter.ProviderParameterNames;
29  import org.apache.maven.surefire.testset.TestSetFailedException;
30  import org.testng.TestNG;
31  import org.testng.xml.XmlSuite;
32  
33  /**
34   * TestNG configurator for 5.3+ versions. TestNG exposes a {@link org.testng.TestNG#configure(java.util.Map)} method.
35   * All suppported TestNG options are passed in String format, except
36   * <code>TestNGCommandLineArgs.LISTENER_COMMAND_OPT</code> which is <code>List&gt;Class&lt;</code>,
37   * <code>TestNGCommandLineArgs.JUNIT_DEF_OPT</code> which is a <code>Boolean</code>,
38   * <code>TestNGCommandLineArgs.SKIP_FAILED_INVOCATION_COUNT_OPT</code> which is a <code>Boolean</code>,
39   * <code>TestNGCommandLineArgs.OBJECT_FACTORY_COMMAND_OPT</code> which is a <code>Class</code>,
40   * <code>TestNGCommandLineArgs.REPORTERS_LIST</code> which is a <code>List&gt;ReporterConfig&lt;</code>.
41   * <p/>
42   * Test classes and/or suite files are not passed along as options parameters, but configured separately.
43   *
44   * @author <a href='mailto:the[dot]mindstorm[at]gmail[dot]com'>Alex Popescu</a>
45   */
46  public class TestNGMapConfigurator
47      implements Configurator
48  {
49      public void configure( TestNG testng, Map options )
50          throws TestSetFailedException
51      {
52          Map convertedOptions = getConvertedOptions( options );
53          testng.configure( convertedOptions );
54      }
55  
56      public void configure( XmlSuite suite, Map options )
57          throws TestSetFailedException
58      {
59          String threadCountString = (String) options.get( ProviderParameterNames.THREADCOUNT_PROP );
60          int threadCount = ( null != threadCountString ) ? Integer.parseInt( threadCountString ) : 1;
61          suite.setThreadCount( threadCount );
62  
63          String parallel = (String) options.get( ProviderParameterNames.PARALLEL_PROP );
64          if ( parallel != null )
65          {
66              suite.setParallel( parallel );
67          }
68      }
69  
70      Map getConvertedOptions( Map options )
71          throws TestSetFailedException
72      {
73          Map convertedOptions = new HashMap();
74          convertedOptions.put( "-mixed", Boolean.FALSE );
75          for ( Iterator it = options.entrySet().iterator(); it.hasNext(); )
76          {
77              Map.Entry entry = (Map.Entry) it.next();
78              String key = (String) entry.getKey();
79              Object val = entry.getValue();
80              if ( "listener".equals( key ) )
81              {
82                  val = AbstractDirectConfigurator.loadListenerClasses( (String) val );
83              }
84              if ( "objectfactory".equals( key ) )
85              {
86                  val = AbstractDirectConfigurator.loadClass( (String) val );
87              }
88              if ( "reporter".equals( key ) )
89              {
90                  // TODO support multiple reporters?
91                  val = convertReporterConfig( val );
92                  key = "reporterslist";
93  
94              }
95              if ( "junit".equals( key ) )
96              {
97                  val = convert( val, Boolean.class );
98              }
99              else if ( "skipfailedinvocationcounts".equals( key ) )
100             {
101                 val = convert( val, Boolean.class );
102             }
103             else if ( "mixed".equals( key ) )
104             {
105                 val = convert( val, Boolean.class );
106             }
107             else if ( "configfailurepolicy".equals( key ) )
108             {
109                 val = convert( val, String.class );
110             }
111             else if ( "group-by-instances".equals( key ) )
112             {
113                 val = convert( val, Boolean.class );
114             }
115             else if ( ProviderParameterNames.THREADCOUNT_PROP.equals( key ) )
116             {
117                 val = convert( val, String.class );
118             }
119             // TODO objectfactory... not even documented, does it work?
120             if ( key.startsWith( "-" ) )
121             {
122                 convertedOptions.put( key, val );
123             }
124             else
125             {
126                 convertedOptions.put( "-" + key, val );
127             }
128         }
129         return convertedOptions;
130     }
131 
132     // ReporterConfig only became available in later versions of TestNG
133     private Object convertReporterConfig( Object val )
134     {
135         final String reporterConfigClassName = "org.testng.ReporterConfig";
136         try
137         {
138             Class reporterConfig = Class.forName( reporterConfigClassName );
139             Method deserialize = reporterConfig.getMethod( "deserialize", new Class[]{ String.class } );
140             Object rc = deserialize.invoke( null, new Object[]{ val } );
141             ArrayList reportersList = new ArrayList();
142             reportersList.add( rc );
143             return reportersList;
144         }
145         catch ( Exception e )
146         {
147             return val;
148         }
149     }
150 
151     protected Object convert( Object val, Class type )
152     {
153         if ( val == null )
154         {
155             return null;
156         }
157         if ( type.isAssignableFrom( val.getClass() ) )
158         {
159             return val;
160         }
161 
162         if ( ( Boolean.class.equals( type ) || boolean.class.equals( type ) ) && String.class.equals( val.getClass() ) )
163         {
164             return Boolean.valueOf( (String) val );
165         }
166 
167         if ( String.class.equals( type ) )
168         {
169             return val.toString();
170         }
171 
172         return val;
173     }
174 }